package me.zhengjie.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import me.zhengjie.domain.FlowConfig;
import me.zhengjie.domain.vo.FlowConfigQueryCriteria;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.mapper.FlowConfigToolMapper;
import me.zhengjie.service.FlowConfigToolService;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @author 18485
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "Flow")
public class FlowConfigToolServiceImpl extends ServiceImpl<FlowConfigToolMapper,FlowConfig> implements FlowConfigToolService {

    @Autowired
    ProcessEngine processEngine;

    @Autowired
    FlowConfigToolMapper flowConfigToolMapper;

    /**
     * 工作流部署（添加、编辑）
     *
     * @param map 流程
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addFlow(@NotNull Map<String, String> map) {
        try {
            String name = map.get("name");
            String xml = map.get("xml");
            String key = map.get("key");
            long id = Long.parseLong(map.get("id"));
            RepositoryService repositoryService = processEngine.getRepositoryService();
            // 创建新流程
            Deployment deployment = repositoryService.createDeployment()
                    .addString(name + ".bpmn", xml)
                    .deploy();

            System.out.println("id : " + id);
            System.out.println("添加id : " + deployment.getId());
            System.out.println("添加key : " + key);
            FlowConfig flowConfig = new FlowConfig();
            flowConfig.setFlowName(name);
            flowConfig.setFlowId(deployment.getId());
            flowConfig.setFlowKey(key);
            flowConfig.setStatus(1);
            save(flowConfig);
        } catch (Exception e) {
            throw new BadRequestException("添加失败,请检查数据");
        }
    }




    /**
     * 工作流返回（返回xml）
     *
     * @param map   查询id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String infoFlow(Map<String, String> map) {
        try {
            String id = map.get("id");
            String name = map.get("name");
            FlowConfig flowConfig = baseMapper.selectOne(new QueryWrapper<FlowConfig>().eq("flow_name", name));
            // 流程查询
            RepositoryService repositoryService = processEngine.getRepositoryService();
            InputStream resourceAsStream = repositoryService.getResourceAsStream(flowConfig.getFlowId(), name + ".bpmn");

            // Java流转String
            String resultXml = new BufferedReader(new InputStreamReader(resourceAsStream, "utf-8"))
                    .lines().collect(Collectors.joining(System.lineSeparator()));
            return resultXml;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "查询失败";
    }

    /**
     * 工作流删除
     * @param map
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteFlow(Map<String,String> map) {
        try {
            String id = map.get("id");
            RepositoryService repositoryService = processEngine.getRepositoryService();
            // 设置为TRUE 级联删除流程定义，及时流程有实例启动，也可以删除，设置为false 非级联删除操作。
            repositoryService.deleteDeployment(id);
            System.out.println("删除id : " + id);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException( "删除失败");
        }
    }
//
    /**
     * 工作流部署列表查询
     *
     */
    @Transactional(rollbackFor = Exception.class)
    public List<FlowConfig> getDeployList(FlowConfigQueryCriteria criteria) {
        try {
            RepositoryService repositoryService = processEngine.getRepositoryService();
            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
            List<FlowConfig> flowConfigList = flowConfigToolMapper.findAll(criteria);
            System.out.println("list : " + list);
            System.out.println("flowConfigList: " + flowConfigList);
            return flowConfigList;
        } catch (Exception e) {
            throw  new BadRequestException("数据异常，查询失败");
        }
    }

    /**
     * 启动流程实例
     *
     * @param userId 发起人
     * @param key    流程key
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void deploymentRun(String userId, String key) {
        try {
            RuntimeService runtimeService = processEngine.getRuntimeService();
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key);
            //获取流程实例的相关信息
            System.out.println("流程定义的id = " + processInstance.getProcessDefinitionId());
            System.out.println("流程实例的id = " + processInstance.getId());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException("失败");
        }
    }

    /**
     * 查询流程任务
     *
     * @param userId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void infoTask(String userId) {
        try {
            TaskService taskService = processEngine.getTaskService();
            // 查询多人任务
            List<Task> taskList = taskService.createTaskQuery().taskCandidateUser(userId).list();
            System.out.println("taskList" + taskList);
            //遍历任务列表
            for (Task task : taskList) {
                System.out.println("流程定义id = " + task.getProcessDefinitionId());
                System.out.println("流程实例id = " + task.getProcessInstanceId());
                System.out.println("任务id = " + task.getId());
                System.out.println("任务名称 = " + task.getName());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException("失败");
        }
    }

    /**
     * 执行流程任务
     *
     * @param userId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void makeTask(String userId) {
        try {
            TaskService taskService = processEngine.getTaskService();
            // 查询个人任务
            List<Task> list = taskService.createTaskQuery().taskCandidateUser(userId).list();
            System.out.println("taskList" + list);
            for (Task task : list) {
                taskService.complete(task.getId());
                System.out.println("task.getId()" + task.getId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException( "失败" );
        }
    }

    /**
     * 查询历史流程
     *
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void taskHistory() {
        try {
            HistoryService historyService = processEngine.getHistoryService();
            List<HistoricActivityInstance> activities = historyService.createHistoricActivityInstanceQuery()
                    // .processInstanceId("12501") // 特定的实例
                    .finished() // 完成的
                    // .orderByHistoricActivityInstanceEndTime().asc() // 根据实例完成时间升序排列
                    .list();

            for (HistoricActivityInstance activity : activities) {
                System.out.println("id:" + activity.getActivityId() + "  任务名：" + activity.getActivityName() + "  类型：" + activity.getActivityType() + "  持续时间:" + activity.getDurationInMillis());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException( "失败" );
        }
    }
}